-module(cdr_to_cvs).
-include("subscriber.hrl").
-include("cdr.hrl").
-include("network.hrl").
-export([do/1,record_to_target/1]).

do(Sub) ->
	record_to_target(Sub).
record_to_target(Cdr) when (is_record(Cdr,lte_s1_cdr)) ->
  {MMEs,ENodeBs} = Cdr#lte_s1_cdr.access_info,
  {
   RRC_Con_Reason,
   End_Reason,
   Duration,
   Start_Time,
   End_Time,
   User_Id,
   End_Mode,
   Aux_Info,
   Rate,
   Rab_Info,
   MME,
   ENodeB,
   CellId
  } = {
      list_to_binary(atom_to_list(Cdr#lte_s1_cdr.rrc_con_reason)),
      term_to_string({end_reason,Cdr#lte_s1_cdr.end_reason}),
	  term_to_string({duration,Cdr#lte_s1_cdr.start_time,Cdr#lte_s1_cdr.end_time}),
	  term_to_string({date_time,Cdr#lte_s1_cdr.start_time}),
      term_to_string({date_time,Cdr#lte_s1_cdr.end_time}),
      term_to_string({user_id,Cdr#lte_s1_cdr.user_id}),
      list_to_binary(atom_to_list(Cdr#lte_s1_cdr.end_mode)),
      term_to_string({aux_info,Cdr#lte_s1_cdr.aux_info,""}),
	  term_to_string({rate,Cdr#lte_s1_cdr.rate}),
	  term_to_string({rab_info,Cdr#lte_s1_cdr.rab_info," "}),
      term_to_string({ip,MMEs}),
      term_to_string({ip,ENodeBs}),
      term_to_string({cellid,Cdr#lte_s1_cdr.cellid})
  },
  <<
    RRC_Con_Reason/binary,
    ";",
		End_Reason/binary,
	";",
		Duration/binary,
    ";",
		Start_Time/binary,
    ";",
		End_Time/binary,
    ";",
		User_Id/binary,
    ";",
		End_Mode/binary,
    ";",
		Aux_Info/binary,
    ";",
		Rate/binary,
    ";",
    Rab_Info/binary,
    ";",
		MME/binary,
    ";",
		ENodeB/binary,
    ";",
    CellId/binary
  >>.
term_to_string(Integer) when is_integer(Integer) ->
	list_to_binary(io_lib:format("~B",[Integer]));
term_to_string({_,unknown}) ->
	<<"unknown">>;
term_to_string({mac,<<MAC1:8,MAC2:8,MAC3:8,MAC4:8,MAC5:8,MAC6:8>>}) ->
	list_to_binary(io_lib:format("~.16B:~.16B:~.16B:~.16B:~.16B:~.16B",[MAC1,MAC2,MAC3,MAC4,MAC5,MAC6]));

term_to_string({ip,{IP1,IP2,IP3,IP4}}) ->
	list_to_binary(io_lib:format("~B.~B.~B.~B",[IP1,IP2,IP3,IP4]));
term_to_string({ip,<<IP1:8,IP2:8,IP3:8,IP4:8>>}) ->
	list_to_binary(io_lib:format("~B.~B.~B.~B",[IP1,IP2,IP3,IP4]));
term_to_string({string,Str}) ->
	list_to_binary(Str);
	
term_to_string({date_time,{little,Capture_Time}}) ->
	<<Sec:32/integer-unsigned-little,USec:32/integer-unsigned-little>> = Capture_Time,
    term_to_string({date_time,{calendar:gregorian_seconds_to_datetime(Sec),USec}});

term_to_string({date_time,{big,Capture_Time}}) ->
	<<Sec:32/integer-unsigned-big,USec:32/integer-unsigned-big>> = Capture_Time,
    term_to_string({date_time,{calendar:gregorian_seconds_to_datetime(Sec),USec}});
	
term_to_string({date_time,{{{Year,Month,Day},{Hour,Min,Sec}},USec}}) ->
	list_to_binary(io_lib:format("~p-~p-~p ~p:~p:~p ~p",[Year + 1970,Month,Day,Hour,Min,Sec,USec]));
	
term_to_string({duration,{Endian,Start_Time},{Endian,End_Time}}) ->
	{SecStart,USecStart} = case Endian of
              little ->
                <<Sec:32/integer-unsigned-little,USec:32/integer-unsigned-little>> = Start_Time,
                {Sec,USec};
              _ ->
                <<Sec:32/integer-unsigned-big,USec:32/integer-unsigned-big>> = Start_Time,
                {Sec,USec}
              end,
	{SecEnd,USecEnd} = case Endian of
              little ->
                <<NSec:32/integer-unsigned-little,NUSec:32/integer-unsigned-little>> = End_Time,
                {NSec,NUSec};
              _ ->
                <<NSec:32/integer-unsigned-big,NUSec:32/integer-unsigned-big>> = End_Time,
                {NSec,NUSec}
              end,
	if 
		USecEnd > USecStart ->
			list_to_binary(io_lib:format("~B:~B",[SecEnd - SecStart,USecEnd - USecStart]));
		true ->
			list_to_binary(io_lib:format("~B:~B",[(SecEnd - 1) - SecStart,(USecEnd + 1000000) - USecStart]))
	end;
term_to_string({duration,_Start,_End}) ->
	list_to_binary(io_lib:format("error",[]));	
term_to_string({user_id,{tmsi,Tmsi}}) ->
	list_to_binary(io_lib:format("tmsi:~.16B",[Tmsi]));
term_to_string({user_id,{imsi,Imsi}}) ->
	list_to_binary(io_lib:format("tmsi:~p",[Imsi]));
term_to_string({user_id,{guti,Guti}}) ->
	list_to_binary(io_lib:format("guti:~p",[Guti]));
term_to_string({rate,{UL,DL}}) ->
	list_to_binary(io_lib:format("UL:~B,DL:~B",[UL,DL]));	
term_to_string({aux_info,[{message,Index}|Other],Cur_Str}) ->
	term_to_string({aux_info,Other,io_lib:format("~s msg:~p",[Cur_Str,Index])});
term_to_string({aux_info,[_Unknown|Other],Cur_Str}) ->
	term_to_string({aux_info,Other,Cur_Str});
term_to_string({aux_info,[],Cur_Str}) ->
	list_to_binary(Cur_Str);
term_to_string({end_reason,Value}) when is_atom(Value) ->
  atom_to_list(Value);
term_to_string({end_reason,{nas,Reason}}) ->
  list_to_binary(io_lib:format("nas release with ~p",[Reason]));
term_to_string({end_reason,{radioNetwork,Reason}}) ->
  list_to_binary(io_lib:format("RN release with ~p",[Reason]));  
term_to_string({end_reason,Value}) ->
  list_to_binary(io_lib:format("~p",[Value]));
term_to_string({rab_info,[{Rab_Id,{IP1,IP2,IP3,IP4},TeId}|Others],Cur_Str}) ->
	term_to_string({rab_info,Others,io_lib:format("~s rab:~p(~p.~p.~p.~p,~.16B)",[Cur_Str,Rab_Id,IP1,IP2,IP3,IP4,TeId])});
term_to_string({rab_info,[],Cur_Str}) ->
	list_to_binary(Cur_Str);
term_to_string({access_info,{MMe, ENodeB}}) ->
  IP1 = term_to_string({ip,MMe}),
  IP2 = term_to_string({ip,ENodeB}),
	<<IP1/binary,",",IP2/binary>>;
term_to_string({cellid,<<PC:28/integer>>}) ->
  list_to_binary(io_lib:format("~.16B",[PC]));
term_to_string(Unknown) ->
	list_to_binary(io_lib:format("uncoded ~p",[Unknown])).
